/****************************************************************************
 * Copyright (C) 2009-2010 SciTouch LLC
 * 
 * This file is part of Indigo toolkit.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 3 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

﻿using System;
using System.Text;
using System.Runtime.InteropServices;

namespace indigo
{
   public unsafe class Cano
   {
      [DllImport("kernel32")]
      static extern IntPtr LoadLibrary(string lpFileName);

      private static bool initialized = false;

      public static void init(string prefix)
      {
         string subprefix = (IntPtr.Size == 8) ? "lib64/" : "lib32/";

         LoadLibrary(prefix + "/" + subprefix + "cano.dll");
         initialized = true;
      }

      public static String getVersion()
      {
         if (!initialized)
            init(".");
         return new String(canoGetVersion());
      }

      public static string getCanonicalSmiles(String molecule, String options)
      {
         return getCanonicalCodeImp(molecule, options, true);
      }

      public static string getLayeredCode(String molecule, String options)
      {
         return getCanonicalCodeImp(molecule, options, false);
      }

      private static string getCanonicalCodeImp(String molecule, String options, bool is_smiles)
      {
         if (!initialized)
            init(".");

         if (canoSetMolecule(molecule) == 0)
            throw new CanoException(new String(canoGetLastError()));

         if (canoSetOptions(options != null ? options : "") == 0)
            throw new CanoException(new String(canoGetLastError()));

         sbyte* canonical_code;

         int ret;
         if (is_smiles)
            ret = canoGetCanonicalSmiles(&canonical_code);
         else
            ret = canoGetLayeredCode(&canonical_code);

         if (ret == 0)
            throw new CanoException(new String(canoGetLastError()));

         return new String(canonical_code);
      }

      [DllImport("cano.dll")]
      private static extern sbyte* canoGetLastError();
      [DllImport("cano.dll")]
      private static extern sbyte* canoGetVersion();
      [DllImport("cano.dll")]
      private static extern int canoSetOptions(string options);
      [DllImport("cano.dll")]
      private static extern int canoSetMolecule(string molecule);
      [DllImport("cano.dll")]
      private static extern int canoGetCanonicalSmiles(sbyte** smiles);
      [DllImport("cano.dll")]
      private static extern int canoGetLayeredCode(sbyte** inchi_code);
   }
}
